package com.global.gbinventory.barang.tablemodel;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.global.gbinventory.barang.model.Gudang;
import com.global.gbinventory.barang.util.TYPE;
import com.global.gbinventory.barang.util.DBMaster;
import com.global.gbinventory.barang.util.CONSTANT;
import com.global.gbinventory.barang.util.STATUS_TYPE;
import com.global.gbinventory.barang.util.Status;
import com.global.gbinventory.main.model.GBTableModel;

public class GudangTableModel extends GBTableModel{

	private static final long serialVersionUID = 3684337086292939668L;
	
	private List<Gudang> gudangList; //list to save all gudang barang according to DB
	private List<Integer> editedGudangList; //list used to save index of all the edited tuple
	
	private DBMaster dbMaster; //utility to communicate with DB
	private TYPE type;
	
	/**
	 * constructor
	 * @param dbMaster
	 */
	public GudangTableModel(DBMaster dbMaster){
		super();
		this.dbMaster = dbMaster;
		gudangList = new ArrayList<Gudang>();
		editedGudangList = new ArrayList<Integer>();
		type = TYPE.GUDANGs;
		initialize();
	}
	
	/**
	 * initialize the needed data
	 */
	private void initialize(){
		initTableData();
	}
	
	/**
	 * initialize the table model using the data from DB
	 * Furthermore, it also initialize the gudangList
	 */
	private void initTableData(){
		List<Object[]> dbTable = dbMaster.getData(type);
		List<Object[]> tmData = new ArrayList<Object[]>();
		Object[] tmCols = null;
		
		for(Object[] obj : dbTable){
			//add data from DB to gudangList
			int id = (Integer) obj[CONSTANT.GUDANG_DB_ID];
			String kode = obj[CONSTANT.GUDANG_DB_KODE].toString();
			String nama = obj[CONSTANT.GUDANG_DB_NAMA].toString();
			String lokasi = obj[CONSTANT.GUDANG_DB_LOKASI].toString();
			Gudang gudang = new Gudang(id, kode, nama, lokasi);
			gudangList.add(gudang);
			
			//add data from DB to table model
			tmCols = new Object[type.getColumnCount()];
			tmCols[CONSTANT.GUDANG_TM_KODE] = kode;
			tmCols[CONSTANT.GUDANG_TM_NAMA] = nama;
			tmCols[CONSTANT.GUDANG_TM_LOKASI] = lokasi;
			tmData.add(tmCols);
		}
		
		setColumnNames(type.getColumnNames());
		setData(tmData);
		
	}
	
	/**
	 * add a new empty row into Tablemodel
	 */
	public void addNewRow(){
		addRow(new Object[]{"", "", ""});
	}
	
	/**
	 * return a new primary key (id) corresponding to 
	 * the autoincrement id in DB
	 * @return
	 */
	public int getNewId(){
		if(!(gudangList.isEmpty())){
			Gudang lastGudang = gudangList.get(gudangList.size() - 1);
			int lastId = lastGudang.getId();
			return lastId + 1;
		}else{
			return 1;
		}
		
	}
	
	public void addEditedTuple(int row){
		if(!(editedGudangList.contains((Object) row))){
			editedGudangList.add(row);
		}
	}
	
	public void delete(int row){
		int totalTuples = gudangList.size();
		
		if(row >= totalTuples){
			removeRow(row);
		}else{
			Gudang gudang = gudangList.get(row);
			int pk = gudang.getId();
			
			try {
				dbMaster.removeTuple(type, pk);
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
			gudangList.remove(row);
			removeRow(row);
		}
	}
	
	/**
	 * method use to save the new and edited tuple
	 */
	public Status save(){
		int start = gudangList.size();
		
		//save all new gudang into DB and add it to gudangList
		if(start < getRowCount()){
			do {
				if(isEmptyTuple(start)){
					removeRow(start);
					
					if(editedGudangList.contains(start)){
						editedGudangList.remove((Object) start);
					}
					
					for(int i : editedGudangList){
						int index = editedGudangList.indexOf((Object) i);
						editedGudangList.set(index, i - 1);
					}
				}else{
					
					try {
						
						Object[] tuple = getTuple(start);
						String kode = tuple[CONSTANT.GUDANG_TM_KODE].toString();
						String nama = tuple[CONSTANT.GUDANG_TM_NAMA].toString();
						String lokasi = tuple[CONSTANT.GUDANG_TM_LOKASI].toString();
						
						if(kode.equals("") || nama.equals("") || lokasi.equals("")){
							return new Status(STATUS_TYPE.ERROR_EMPTY_TUPLE);
						}else{
							
							if(editedGudangList.contains(start)){
								editedGudangList.remove((Object) start);
							}
							
							dbMaster.addNewTuple(type, tuple);
							
							Gudang newGudang = new Gudang(getNewId(), kode, nama, lokasi);
							gudangList.add(newGudang);
							
							start++;
						}
						
					} catch (SQLException e) {
						e.printStackTrace();
					}
					
				}
			} while (start < getRowCount());
		}
		
		//save edited tuple into DB
		for(Integer row : editedGudangList){
			Object[] tuple = getTuple(row);
			String kode = tuple[CONSTANT.GUDANG_TM_KODE].toString();
			String nama = tuple[CONSTANT.GUDANG_TM_NAMA].toString();
			String lokasi = tuple[CONSTANT.GUDANG_TM_LOKASI].toString();
			if(kode.equals("") || nama.equals("") || lokasi.equals("")){
				return new Status(STATUS_TYPE.ERROR_EMPTY_TUPLE);
			}else{
				//edit corresponding gudang in gudangList
				Gudang gudang = gudangList.get(row);
				int pk = gudang.getId();
				gudang.setKode(kode);
				gudang.setNama(nama);
				gudang.setLokasi(lokasi);
				
				//edit corresponding tuple in DB
				try {
					dbMaster.updateTuple(type, pk, tuple);
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		
		editedGudangList.clear();
		return new Status(STATUS_TYPE.SUCCESS);
		
	}
	
	@Override
    public boolean isCellEditable(int row, int col) {
    	return true;
    }
	
	public String[] getAllGudangNames(){
		String[] list = new String[gudangList.size()];
		for(int i = 0; i < gudangList.size(); i++){
			list[i] = gudangList.get(i).getNama();
		}
		
		return list;
	}
	
}
